import interpreter.Memory;
import interpreter.Registers;
import interpreter.operation.Instruct;
import interpreter.operation.Handler;

import java.io.*;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

/**
 * @author Roderland
 * @since 1.0
 */
public class Main {

    public static void main(String[] args) throws FileNotFoundException {
        loadInstruction();

        instructionCycle();

        printResult();
    }

    public static void printResult() {
        print(Registers.EAX.getValue());
    }

    public static void loadInstruction() throws FileNotFoundException {
        BufferedReader reader = new BufferedReader(new InputStreamReader(
                new FileInputStream("src/source/asm")));
        String line = null;
        try {
            while ((line = reader.readLine()) != null) {
                Memory.instructs.add(new Instruct(line));
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public static void instructionCycle() {
        System.out.println("======== asm ========");
        for (Instruct instruct : Memory.instructs) {
            System.out.println(instruct.getSourceCode());
            Class<?>[] parameterType = new Class[2];
            if (instruct.getSrc() != null) {
                if ("REG".equals(instruct.getSrc().getOpType().toString())) {
                    parameterType[0] = Registers.class;
                } else {
                    parameterType[0] = int.class;
                }
            }
            if (instruct.getDest() != null) {
                if ("REG".equals(instruct.getDest().getOpType().toString())) {
                    parameterType[1] = Registers.class;
                } else {
                    parameterType[1] = int.class;
                }
            }

            try {
                Method method = null;
                if (parameterType[0] == null) {
                    method = Handler.class.getMethod(instruct.getOp().getName());
                    method.invoke(Handler.HANDLER);
                } else if (parameterType[1] == null) {
                    method = Handler.class.getMethod(instruct.getOp().getName(), parameterType[0]);
                    method.invoke(Handler.HANDLER, instruct.getSrc().decode());
                } else {
                    method = Handler.class.getMethod(instruct.getOp().getName(), parameterType[0], parameterType[1]);
                    method.invoke(Handler.HANDLER, instruct.getSrc().decode(), instruct.getDest().decode());
                }
            } catch (NoSuchMethodException e) {
                e.printStackTrace();
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            } catch (InvocationTargetException e) {
                e.printStackTrace();
            }
        }
        System.out.println("=====================");
    }

    public static void print(int value) {
        System.out.printf("0x%08x\n", value);
    }
}
